#include <windows.h>
#include <stdio.h>
#include "RealIFeedback.h"

RealIFeedback FeedbackObj;
ITypeInfo *FeedbackTypeInfo;

HRESULT LoadFeedbackTypeInfo()
{
    HRESULT hr;
    ITypeLib *pTypeLib = NULL;
    hr = LoadRegTypeLib(TLBID_IExampleEvts, 1, 0, 0, &pTypeLib);
    if (FAILED(hr)) return hr;
    hr = pTypeLib->GetTypeInfoOfGuid(DIID_IFeedback, &FeedbackTypeInfo);
    pTypeLib->Release();
    if (FAILED(hr)) return hr;
    FeedbackTypeInfo->AddRef();
    return S_OK;
}

HRESULT STDMETHODCALLTYPE RealIFeedback::QueryInterface(REFIID riid, void **ppv)
{
    if (IsEqualIID(riid, IID_IUnknown) ||
        IsEqualIID(riid, IID_IDispatch) ||
        IsEqualIID(riid, DIID_IFeedback))
    {
        *ppv = this;
        AddRef();
        return S_OK;
    }

    *ppv = NULL;
    return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE RealIFeedback::AddRef()
{
    return 1;
}

ULONG STDMETHODCALLTYPE RealIFeedback::Release()
{
    return 1;
}

HRESULT STDMETHODCALLTYPE RealIFeedback::GetTypeInfoCount(UINT *pctinfo)
{
    *pctinfo = 0;
    return S_OK;
}

HRESULT STDMETHODCALLTYPE RealIFeedback::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
    *ppTInfo = NULL;
    return S_OK;
}

HRESULT STDMETHODCALLTYPE RealIFeedback::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
    return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE RealIFeedback::Invoke(DISPID dispIdMember, REFIID riid,
                                                LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
                                                VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
    if (!IsEqualIID(riid, IID_NULL)) return DISP_E_UNKNOWNINTERFACE;
    if (FeedbackTypeInfo == NULL)
    {
        HRESULT hr = LoadFeedbackTypeInfo();
        if (FAILED(hr)) return hr;
    }
    return DispInvoke(this, FeedbackTypeInfo, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
}

HRESULT STDMETHODCALLTYPE RealIFeedback::Callback1()
{
    printf("Callback1 is called.\n");
    return S_OK;
}

HRESULT STDMETHODCALLTYPE RealIFeedback::Callback2()
{
    printf("Callback2 is called.\n");
    return S_OK;
}

HRESULT STDMETHODCALLTYPE RealIFeedback::Callback3()
{
    printf("Callback3 is called.\n");
    return S_OK;
}
